#include <iostream>
#include "Log.hpp"
#include <memory>
#include <list>
#include "InetAddr.hpp"
#include <string.h>
#include <utility>

#include <mysql/mysql.h>

#include <string>
#include <vector>
#include <mysql-cppconn/jdbc/mysql_driver.h>
#include <mysql-cppconn/jdbc/mysql_connection.h>
#include <mysql-cppconn/jdbc/cppconn/statement.h>
#include <mysql-cppconn/jdbc/cppconn/prepared_statement.h>

const std::string global_host = "127.0.0.1";
const std::string global_user = "zj";
const std::string global_passwd = "050716";
const std::string global_db = "ConnectTest";
const unsigned int global_port = 8080;
const std::string global_Begin_Affairs = "begin";

// 采用数据库连接池技术我认为是可行的

enum
{
    FAILED_BEGIN = 1,
    FAILED_SQL = 2,
    FAILED_COMMIT = 3
};

using namespace LogMudule;

class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void Sendto(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &id) = 0;
    virtual void Commit(InetAddr &id) = 0;

private:
};

class User : public UserInterface
{
public:
    User(const InetAddr &id) : _id(id)
    {
    }

    void Sendto(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::INFO) << "send message to" << _id.ID() << message;
        int n = sendto(sockfd, message.c_str(), sizeof(message), 0, _id.GetSockaddr_In(), _id.LenSockaddr_in());
        (void)n;
    }

    bool operator==(const InetAddr &id) override
    {
        return _id == id;
    }

    void Commit(InetAddr &id) override
    {
        return;
    }

    ~User()
    {
    }

private:
    InetAddr _id; // 自己封装的内部含有struct sockaddr ip port
};

// 现在我的任务是把用户信息录入到数据库里

class MySQL_User : public UserInterface
{
public:
    MySQL_User()
    {
        std::cerr << "MySQL_User()" << std::endl;
        mysql = mysql_init(nullptr); // 初始化 MySQL 连接
        if (!mysql)
        {
            std::cerr << "mysql_init failed" << std::endl;
            return;
        }

        if (!mysql_real_connect(mysql, global_host.c_str(), global_user.c_str(), global_passwd.c_str(), global_db.c_str(), global_port, nullptr, 0))
        {
            std::cerr << "mysql_real_connect failed: " << mysql_error(mysql) << std::endl;
            mysql_close(mysql);
            mysql = nullptr;
            return;
        }
        mysql_set_character_set(mysql, "utf8");
        std::cout << "MySQL connection established successfully!" << std::endl;
    }

    /*MySQL_User(const MySQL_User& mu)
    {
        std::cerr << "MySQL_User(const MySQL_User& mu)" << std::endl;
        mysql = mysql_init(nullptr); // 初始化 MySQL 连接
        if (!mysql)
        {
            std::cerr << "mysql_init failed" << std::endl;
            return;
        }

        if (!mysql_real_connect(mysql, global_host.c_str(), global_user.c_str(), global_passwd.c_str(), global_db.c_str(), global_port, nullptr, 0))
        {
            std::cerr << "mysql_real_connect failed: " << mysql_error(mysql) << std::endl;
            mysql_close(mysql);
            mysql = nullptr;
            return;
        }
        mysql_set_character_set(mysql, "utf8");
        std::cout << "MySQL connection established successfully!" << std::endl;
    }*/

    void Sendto(int sockfd, const std::string &message) override
    {
        return;
    }

    bool operator==(const InetAddr &id) override
    {
        return false;
    }

    void Commit(InetAddr &id)
    {

        if (!mysql)
        {
            std::cerr << "MySQL connection is not initialized" << std::endl;
            return;
        }

        int port = id.GetPort();
        std::string ip = id.GetIp();

        std::cout << "IP: " << ip << ", Port: " << port << std::endl;

        MYSQL_STMT *stmt;
        MYSQL_BIND bind[2];

        stmt = mysql_stmt_init(mysql);
        if (!stmt)
        {
            std::cerr << "mysql_stmt_init() failed" << std::endl;
            return;
        }

        const char *query = "INSERT INTO chatuser (IP, Port) VALUES (?, ?)";
        if (mysql_stmt_prepare(stmt, query, strlen(query)))
        {
            std::cerr << "mysql_stmt_prepare() failed: " << mysql_stmt_error(stmt) << std::endl;
            mysql_stmt_close(stmt);
            return;
        }

        memset(bind, 0, sizeof(bind));
        bind[0].buffer_type = MYSQL_TYPE_STRING;
        bind[0].buffer = (char *)ip.c_str();
        bind[0].buffer_length = ip.length();

        bind[1].buffer_type = MYSQL_TYPE_LONG;
        bind[1].buffer = (char *)&port;
        bind[1].is_unsigned = true;

        if (mysql_stmt_bind_param(stmt, bind))
        {
            std::cerr << "mysql_stmt_bind_param() failed: " << mysql_stmt_error(stmt) << std::endl;
            mysql_stmt_close(stmt);
            return;
        }

        if (mysql_stmt_execute(stmt))
        {
            std::cerr << "mysql_stmt_execute() failed: " << mysql_stmt_error(stmt) << std::endl;
        }
        else
        {
            std::cout << "Data inserted successfully!" << std::endl;
        }

        mysql_stmt_close(stmt);
        /*int port = id.GetPort();
        std::string ip = id.GetIp();
        std::cout << "发送失败" << std::endl;
        // 创建 SQL 查询
        // 创建 SQL 查询
        std::string sql = "INSERT INTO chatuser (ip, port) VALUES ('127.0.0.1', 11);";
        if (mysql_query(mysql, sql.c_str()))
        {
            std::cerr << "Error: " << mysql_error(mysql) << std::endl;
        }
        else
        {
            std::cout << "Data inserted successfully!" << std::endl;
        }*/
    }

    ~MySQL_User()
    {
        std::cout << "MySQL_User" << std::endl;
        // 关闭连接
        if (mysql)
        {
            mysql_close(mysql);
        }
    }

private:
    MYSQL *mysql;
};

class UserManger
{
public:
    UserManger()
    {
    }

    void AddUser(InetAddr &id) // 添加用户
    {
        Lockguard lock(mutex);
        // 检查是否已经存在
        for (auto user : online_user)
        {
            if (*user == id)
            {
                LOG(LogLevel::INFO) << id.ID();
                LOG(LogLevel::INFO) << id.ID() << "用户已经存在";
                return;
            }
        }
        // 不存在
        User user(id);
        online_user.push_back(std::make_shared<User>(user));
    }

    void DelUser()
    {
        // 用户退出删除用户
    }
    // 创建了用户就用数据库插入

    // 这里一定传引用，值传递的话，智能指针此时就是野指针
    //template<typename T>
    /*void MysqlInit(MySQL_User my) // 一开始就调用，然后开始位置就是0
    {
        //std::forward<T>(my);
        Lockguard lock(mutex);


        online_user.push_front(std::make_shared<MySQL_User>(my));//这里my如果是值传递，那么后续通过Online的链表里存放的就是i一个野指针，因为my出了作用域就析构了
    }*/

    void MysqlInit() // 一开始就调用，然后开始位置就是0
    {
        //std::forward<T>(my);
        Lockguard lock(mutex);


        online_user.push_front(std::make_shared<MySQL_User>());//这里my如果是值传递，那么后续通过Online的链表里存放的就是i一个野指针，因为my出了作用域就析构了
    }

    void MysqlInsert(InetAddr &id)
    {
        Lockguard lock(mutex);
        if (!online_user.empty())
        {
            MySQL_User *mysql_user = dynamic_cast<MySQL_User *>(online_user.front().get());
            if (mysql_user)
            {
                mysql_user->Commit(id);
            }
            else
            {
                std::cerr << "First element is not a MySQL_User object" << std::endl;
            }
        }
        else
        {
            std::cerr << "No MySQL_User object in the list" << std::endl;
        }
    }

    void Router(int sockfd, const std::string &message)
    {
        Lockguard lock(mutex);
        for (auto user : online_user)
        {
            user->Sendto(sockfd, message);
        }
        return;
    }

    ~UserManger()
    {
    }

private:
    std::list<std::shared_ptr<UserInterface>> online_user;
    Mutex mutex;
};
